const http = require('http');
const WebSocket = require('ws');

// 测试配置
const CONFIG = {
  server: {
    host: 'localhost',
    port: 3000,
    protocol: 'http'
  },
  testUser: {
    mobile: '17091271111',
    password: '123456',
    passwordHash: 'e10adc3949ba59abbe56e057f20f883e'
  }
};

class Test4430Format {
  constructor() {
    this.token = null;
    this.userId = null;
    this.ws = null;
    this.characters = [];
    this.selectedCharacter = null;
  }

  async runTest () {
    console.log('🧪 开始测试4430指令数据格式...\n');
    console.log('测试目标：验证4430指令返回的数据格式是否符合标准\n');

    try {
      await this.testHttpLogin();
      await this.testWebSocketConnection();
      await this.testQueryCharacters();

      if (this.characters.length === 0) {
        await this.testCreateCharacter();
        await this.testQueryCharacters();
      }

      await this.testSelectCharacter();
      await this.test4430Format();
      await this.testDisconnect();
    } catch (error) {
      console.error('❌ 测试过程中发生错误:', error.message);
    }
  }

  async testHttpLogin () {
    console.log('🔐 步骤1: HTTP登录测试...');
    try {
      await this.registerUser();
      const loginData = await this.makeHttpRequest('/user-service/user/login', 'POST', {
        mobile: CONFIG.testUser.mobile,
        pwd: CONFIG.testUser.passwordHash
      });

      if (loginData.code === 0 && loginData.data) {
        this.userId = loginData.data.userId;
        this.token = loginData.data.accessToken;
        console.log(`✅ 登录成功: userId=${this.userId}`);
      } else {
        throw new Error(`登录失败: ${loginData.msg || '未知错误'}`);
      }
    } catch (error) {
      console.log('❌ 登录失败:', error.message);
      throw error;
    }
  }

  async registerUser () {
    try {
      const res = await this.makeHttpRequest('/user-service/user/register', 'POST', {
        mobile: CONFIG.testUser.mobile,
        pwd: CONFIG.testUser.passwordHash,
        captcha: '123456'
      });
      console.log('📝 用户注册成功', res);
    } catch (error) {
      if (error.message.includes('MOBILE_EXISTS') || error.message.includes('已存在')) {
        console.log('👤 用户已存在，跳过注册');
      } else {
        console.log('⚠️ 注册失败:', error.message);
      }
    }
  }

  async testWebSocketConnection () {
    console.log('\n🔌 步骤2: WebSocket连接测试...');
    return new Promise((resolve, reject) => {
      try {
        const wsUrl = `ws://${CONFIG.server.host}:${CONFIG.server.port}/user-service/websocket?t=${this.token}`;
        this.ws = new WebSocket(wsUrl);

        this.ws.on('open', async () => {
          console.log('✅ WebSocket连接成功');
          this.setupMessageHandler();
          await this.delay(500);
          resolve();
        });

        this.ws.on('error', (error) => {
          console.log('❌ WebSocket连接失败:', error.message);
          reject(error);
        });

        this.ws.on('close', () => {
          console.log('🔌 WebSocket连接已关闭');
        });

        setTimeout(() => {
          if (this.ws.readyState === WebSocket.CONNECTING) {
            this.ws.close();
            reject(new Error('连接超时'));
          }
        }, 10000);
      } catch (error) {
        reject(error);
      }
    });
  }

  setupMessageHandler () {
    this.ws.on('message', (data) => {
      try {
        const message = JSON.parse(data.toString());
        console.log('📨 收到消息:', JSON.stringify(message, null, 2));
        this.handleWebSocketResponse(message);
      } catch (error) {
        console.error('❌ 消息解析失败:', error.message);
      }
    });
  }

  handleWebSocketResponse (message) {
    const { act_id, code, roleList, data, msg } = message;

    switch (act_id) {
      case 3: // 角色列表
        if (code === 0 && roleList) {
          this.characters = roleList;
          console.log(`✅ 获取角色列表成功: ${roleList.length} 个角色`);
        }
        break;
      case 5: // 创建角色
        if (code === 0) {
          console.log('✅ 角色创建成功');
        } else {
          console.log(`❌ 角色创建失败: ${msg || '未知错误'}`);
        }
        break;
      case 4: // 选择角色
        if (code === 0) {
          console.log('✅ 角色选择成功');
        } else {
          console.log(`❌ 角色选择失败: ${msg || '未知错误'}`);
        }
        break;
      case 4430: // 赤壁历史记录
        this.validate4430Format(message);
        break;
    }
  }

  validate4430Format (message) {
    console.log('\n🔍 验证4430指令数据格式...');

    // 检查基本结构
    if (message.act_id !== 4430) {
      console.log('❌ act_id不正确，期望: 4430, 实际:', message.act_id);
      return;
    }

    if (message.code !== 0) {
      console.log('❌ code不正确，期望: 0, 实际:', message.code);
      return;
    }

    if (!message.list || !Array.isArray(message.list)) {
      console.log('❌ list字段缺失或不是数组');
      return;
    }

    console.log('✅ 基本结构验证通过');

    // 检查list中的数据结构
    if (message.list.length > 0) {
      const firstItem = message.list[0];
      console.log('\n📋 第一个数据项结构:');
      console.log(JSON.stringify(firstItem, null, 2));

      // 检查必需字段
      const requiredFields = ['creationTime', 'gold', 'result', 'rndNum', 'sliver'];
      const missingFields = requiredFields.filter(field => !(field in firstItem));

      if (missingFields.length > 0) {
        console.log('❌ 缺少必需字段:', missingFields);
      } else {
        console.log('✅ 必需字段验证通过');
      }

      // 检查字段类型
      if (typeof firstItem.gold !== 'number') {
        console.log('❌ gold字段类型错误，期望: number, 实际:', typeof firstItem.gold);
      }
      if (typeof firstItem.result !== 'number') {
        console.log('❌ result字段类型错误，期望: number, 实际:', typeof firstItem.result);
      }
      if (typeof firstItem.rndNum !== 'number') {
        console.log('❌ rndNum字段类型错误，期望: number, 实际:', typeof firstItem.rndNum);
      }
      if (typeof firstItem.sliver !== 'number') {
        console.log('❌ sliver字段类型错误，期望: number, 实际:', typeof firstItem.sliver);
      }
      if (typeof firstItem.creationTime !== 'string') {
        console.log('❌ creationTime字段类型错误，期望: string, 实际:', typeof firstItem.creationTime);
      }

      console.log(`\n📊 数据统计: 共 ${message.list.length} 条记录`);
    } else {
      console.log('⚠️ list为空，无法验证数据结构');
    }
  }

  async testQueryCharacters () {
    console.log('\n👥 步骤3: 查询角色列表...');
    return new Promise((resolve) => {
      if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
        resolve();
        return;
      }

      const timeout = setTimeout(() => {
        this.ws.removeListener('message', handler);
        console.log('⚠️ 查询角色超时');
        resolve();
      }, 10000);

      const handler = (data) => {
        try {
          const message = JSON.parse(data.toString());
          if (message && message.act_id === 3) {
            clearTimeout(timeout);
            this.ws.removeListener('message', handler);
            resolve();
          }
        } catch (_) { }
      };

      this.ws.on('message', handler);
      this.ws.send(JSON.stringify({ c: 3, d: null }));
    });
  }

  async testCreateCharacter () {
    console.log('\n👤 步骤4: 创建角色...');
    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      return;
    }

    const createData = {
      c: 5,
      d: {
        name: '测试角色',
        sex: 1,
        roleType: 1,
        headIndex: 2
      }
    };

    console.log(`📤 发送创建角色请求:`, JSON.stringify(createData, null, 2));
    this.ws.send(JSON.stringify(createData));

    await this.delay(2000);
  }

  async testSelectCharacter () {
    console.log('\n🎯 步骤5: 选择角色...');
    if (this.characters.length === 0) {
      console.log('⚠️ 没有可选择的角色');
      return;
    }

    return new Promise((resolve) => {
      if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
        resolve();
        return;
      }

      const targetCharacter = this.characters[0];
      const responseHandler = (data) => {
        try {
          const message = JSON.parse(data.toString());
          if (message.act_id === 4) {
            this.ws.removeListener('message', responseHandler);

            if (message.code === 0) {
              this.selectedCharacter = targetCharacter;
              console.log(`✅ 角色选择成功: ${targetCharacter.name} (ID: ${targetCharacter.id})`);
              setTimeout(() => resolve(), 2000);
            } else {
              console.log(`❌ 角色选择失败: ${message.msg || '未知错误'}`);
              resolve();
            }
          }
        } catch (error) {
          this.ws.removeListener('responseHandler');
          resolve();
        }
      };

      this.ws.on('message', responseHandler);
      this.ws.send(JSON.stringify({
        c: 4,
        d: { characterId: targetCharacter.id }
      }));

      setTimeout(() => {
        this.ws.removeListener('message', responseHandler);
        resolve();
      }, 10000);
    });
  }

  async test4430Format () {
    console.log('\n🧪 步骤6: 测试4430指令数据格式...');

    if (!this.ws || this.ws.readyState !== WebSocket.OPEN) {
      console.log('❌ WebSocket未连接');
      return;
    }

    console.log('📤 发送4430指令请求...');
    this.ws.send(JSON.stringify({
      c: 4430,
      d: { pageNum: 0 }
    }));

    // 等待响应
    await this.delay(5000);
  }

  async testDisconnect () {
    console.log('\n🔌 步骤7: 断开连接...');
    if (this.ws) {
      this.ws.close();
      console.log('✅ WebSocket连接已关闭');
    }
  }

  async makeHttpRequest (path, method = 'GET', data = null) {
    return new Promise((resolve, reject) => {
      const options = {
        hostname: CONFIG.server.host,
        port: CONFIG.server.port,
        path: path,
        method: method,
        headers: {
          'Content-Type': 'application/json',
        }
      };

      if (data) {
        const postData = JSON.stringify(data);
        options.headers['Content-Length'] = Buffer.byteLength(postData);
      }

      const req = http.request(options, res => {
        let body = '';
        res.on('data', (chunk) => { body += chunk; });
        res.on('end', () => {
          try {
            const responseData = JSON.parse(body);
            if (res.statusCode >= 200 && res.statusCode < 300) {
              resolve(responseData);
            } else {
              reject(new Error(`HTTP ${res.statusCode}: ${responseData.message || body}`));
            }
          } catch (error) {
            if (res.statusCode >= 200 && res.statusCode < 300) {
              resolve(body);
            } else {
              reject(new Error(`HTTP ${res.statusCode}: ${body}`));
            }
          }
        });
      });

      req.on('error', (error) => { reject(error); });
      if (data) { req.write(JSON.stringify(data)); }
      req.end();
    });
  }

  async delay (ms) {
    return new Promise(resolve => setTimeout(resolve, ms));
  }
}

async function main () {
  const tester = new Test4430Format();
  await tester.runTest();
}

if (require.main === module) {
  main().catch((error) => {
    console.error('💥 测试脚本执行失败:', error.message);
    process.exit(1);
  });
}

module.exports = Test4430Format; 